package com.ygq.Impl;

import BO.EncodeTestInputBO;
import DO.*;
import DTO.*;
import Exceptions.EncodeTestNoLessOneException;
import Exceptions.QuestionNumberExistedException;
import VO.EncodeExampleVO;
import VO.EncodeQuestionVO;
import VO.EncodeTestVO;
import com.ygq.EncodeQuestionService;
import mapper.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import result.PageResult;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Service
public class EncodeQuestionServiceImpl implements EncodeQuestionService {

    @Autowired
    private EncodeQuestionMapper encodeQuestionMapper;

    @Autowired
    private EncodeExampleMapper encodeExampleMapper;

    @Autowired
    private EncodeTestDataTypeMapper encodeTestDataTypeMapper;

    @Autowired
    private EncodeTestMapper encodeTestMapper;

    @Autowired
    private EncodeTestDataMapper encodeTestDataMapper;

    // 分页查询
    public PageResult getEncodeQuestion(PageJudgeQuestionDTO pageQuestionDTO) {
        PageResult pageResult = new PageResult();
        // 第一次查询 查询总数
        Integer total = encodeQuestionMapper.getTotal(pageQuestionDTO);

        // 第二次查询 查询分页数据
        /*
         * 这里将getCurrentPage作为 (currentPage - 1) * pageSize;
         */
        pageQuestionDTO.setCurrentPage( (pageQuestionDTO.getCurrentPage() - 1) * pageQuestionDTO.getPageSize());
        List<EncodeQuestionVO> list = encodeQuestionMapper.page(pageQuestionDTO);
        pageResult.setTotal(total);
        pageResult.setRecords(list);
        return pageResult;
    }

    // 根据题目id获取改题目的结果示例
    public EncodeExampleVO getEncodeExampleByEncodeId(Integer id,Integer order) {
        return encodeExampleMapper.getEncodeExampleByEncodeId(id,order);
    }

    // 获取结果示例的数量
    public Integer getEncodeExampleNumberByEncodeId(Integer id) {
        return encodeExampleMapper.getEncodeExampleNumberByEncodeId(id);
    }

    // 修改编程题测试用例
    public void UpdateEncodeExampleById(UpdateEncodeExampleDTO updateEncodeExampleDTO) {
        encodeExampleMapper.UpdateById(updateEncodeExampleDTO);
    }

    // 修改编程题
    public void updateEncodeQuestion(UpdateEncodeQuestionDTO updateEncodeQuestionDTO) {
        encodeQuestionMapper.updateEncodeQuestion(updateEncodeQuestionDTO);
    }

    // 删除编程结果示例
    @Transactional
    public void deleteEncodeExample(Integer id,Integer encodeExampleId) {
        encodeExampleMapper.deleteById(id);
        // 删除之后重新排序
        // 思路，查询出所有的编程示例
        List<EncodeExampleDO> list = encodeExampleMapper.getEncodeExampleListByEncodeId(encodeExampleId);
        for (int i = 0; i < list.size(); i++) {
            list.get(i).setOrder(i+1);
        }
        // 重新设置序号
        for (EncodeExampleDO encodeExampleDO : list) {
            encodeExampleMapper.updateOrder(encodeExampleDO);
        }
    }

    // 添加编程题示例
    public void AddEncodeExample(AddEncodeExampleDTO addEncodeExampleDTO) {
        EncodeExampleDO encodeExampleDO = new EncodeExampleDO();
        BeanUtils.copyProperties(addEncodeExampleDTO,encodeExampleDO);
        encodeExampleDO.setCreateTime(LocalDateTime.now());
        // 还要设置顺序
        List<EncodeExampleDO> list = encodeExampleMapper.getEncodeExampleListByEncodeId(addEncodeExampleDTO.getEncodeId());
        int order = 0;
        for (EncodeExampleDO exampleDO : list) {
            if (exampleDO.getOrder()>order){
                order=exampleDO.getOrder();
            }
        }
        encodeExampleDO.setOrder(order+1);
        encodeExampleMapper.addEncodeExample(encodeExampleDO);
    }

    // 获取数据类型
    public List<EncodeTestDataTypeDO> getType() {
        return encodeTestDataTypeMapper.getType();
    }

    // 获取测试用例的数量
    public Integer getEncodeTestNumber(Integer id) {
        return encodeTestMapper.getEncodeTestNumber(id);
    }

    // 获取测试用例
    public EncodeTestVO getEncodeTest(Integer id, Integer order) {
        // 先创建一个VO对象
        EncodeTestVO encodeTestVO = new EncodeTestVO();

        // 在test表里里面查询 id，output出来 // 不能使用Beanutils，因为 encodeTestVO 的input是集合
        EncodeTestDO encodeTestDO = encodeTestMapper.getByIdAndOrder(id,order);
        encodeTestVO.setId(encodeTestDO.getId());
        encodeTestVO.setOutput(encodeTestDO.getOutput());

        // 然后查询encode_test_data表，查询出参数来 这个list需要按照 paramOrder 排序
        List<EncodeTestInputBO> list =  encodeTestDataMapper.getListById(encodeTestDO.getId());
        encodeTestVO.setInput(list);
        return encodeTestVO;
    }

    /**
     * 修改测试用例
     * @param updateEncodeTestDTO
     */
    @Transactional
    public void updateEncodeTest(UpdateEncodeTestDTO updateEncodeTestDTO) {
        // 第一步：修改主表Test
        encodeTestMapper.updateById(updateEncodeTestDTO.getId(),updateEncodeTestDTO.getOutput(),updateEncodeTestDTO.getInput().size());

        // 第二步，删除附表参数表的关于这个测试用例的全部参数信息
        encodeTestDataMapper.deleteByTestId(updateEncodeTestDTO.getId());

        // 第三步，重新添加这个测试用例的参数信息
        // 1. 利用这个 updateEncodeTestDTO 查询出来这个编程题的全部信息，其实只需要 id encodeId
        EncodeTestDO encodeTestDO = encodeTestMapper.getEncodeIdById(updateEncodeTestDTO.getId());

        // 利用这个 encodeId 和 encodeTestVO.input 添加参数信息
        List<EncodeTestDataDO> list = new ArrayList<>();
        if (updateEncodeTestDTO.getInput().isEmpty()){
            return;
        }
        for (int i = 0; i < updateEncodeTestDTO.getInput().size(); i++) {
            EncodeTestDataDO encodeTestDataDO = new EncodeTestDataDO();
            //将input的每条信息赋值给encodeTestDataDO，type，data，paramOrder
            BeanUtils.copyProperties(updateEncodeTestDTO.getInput().get(i),encodeTestDataDO);

            // 将编程题id赋值给 encodeTestDataDO (冗余)
            encodeTestDataDO.setEncodeId(encodeTestDO.getEncodeId());
            // 将测试表的id赋值给 encodeTestDataDO
            encodeTestDataDO.setTestId(encodeTestDO.getId());
            // 设置创建时间
            encodeTestDataDO.setCreateTime(LocalDateTime.now());
            // 全部添加到list集合
            list.add(encodeTestDataDO);
        }
        encodeTestDataMapper.insert(list);
    }

    // 删除测试用例
    @Transactional
    public void deleteEncodeTest(Integer id) {
        // 第一步， 查询出编程题id是多少，然后根据编程题id查询有几套测试用例，如果只有一套测试用例，则报异常
        EncodeTestDO encodeTestDO = encodeTestMapper.getEncodeIdById(id);
        Integer number = encodeTestMapper.getEncodeTestNumber(encodeTestDO.getEncodeId());
        if (number==1){
            // 抛出异常，表示编程题的测试用例不能少于一个
            throw new EncodeTestNoLessOneException();
        }
        // 如果满足，首先，将这个数量保存到编程题中
        encodeQuestionMapper.updateOrders(number-1,encodeTestDO.getEncodeId());
        // 其次删除测试表中的这条数据
        encodeTestMapper.deleteById(id);
        // 再根据这个id删除测试表的参数附表的参数信息
        encodeTestDataMapper.deleteByTestId(id);

    }

    // 添加测试用例
    @Transactional
    public void addTest(UpdateEncodeTestDTO updateEncodeTestDTO) {
        // 1.首先将这个问题表的测试用例数量 +1
        Integer orders = encodeQuestionMapper.getOrderById( updateEncodeTestDTO.getId());
        encodeQuestionMapper.updateOrders(orders+1,updateEncodeTestDTO.getId());
        // 2. 添加 encode_test 的数据
        // 先根据编程题id查询这个题目有多少套测试用例
        Integer number = encodeTestMapper.getEncodeTestNumber(updateEncodeTestDTO.getId());
        EncodeTestDO encodeTestDO = new EncodeTestDO();
        encodeTestDO.setEncodeId(updateEncodeTestDTO.getId());
        encodeTestDO.setOrder(number+1);
        encodeTestDO.setParamNumber(updateEncodeTestDTO.getInput().size());
        encodeTestDO.setOutput(updateEncodeTestDTO.getOutput());
        encodeTestDO.setCreateTime(LocalDateTime.now());

        encodeTestMapper.insert(encodeTestDO);
        // 3. 向encode_test_data 添加数据
        if (updateEncodeTestDTO.getInput().isEmpty()){
            return;
        }
        List<EncodeTestDataDO> list = new ArrayList<>();
        for (int i = 0; i < updateEncodeTestDTO.getInput().size(); i++) {
            EncodeTestDataDO encodeTestDataDO = new EncodeTestDataDO();
            BeanUtils.copyProperties(updateEncodeTestDTO.getInput().get(i),encodeTestDataDO);
            encodeTestDataDO.setEncodeId(updateEncodeTestDTO.getId());
            encodeTestDataDO.setTestId(encodeTestDO.getId());
            encodeTestDataDO.setCreateTime(LocalDateTime.now());

            list.add(encodeTestDataDO);
        }
        encodeTestDataMapper.insert(list);
    }

    // 添加编程题
    public void addEncode(AddEncodeDTO addEncodeDTO) {
        // 第一步，判断编号是否重复
        List<String> list = encodeQuestionMapper.getQuestionNumber();
        for (int i = 0; i < list.size(); i++) {
            // 抛出异常，编号重复
            if (list.get(i).equals(addEncodeDTO.getQuestionNumber())) throw new QuestionNumberExistedException();
        }
        // 第二步，插入数据
        EncodeQuestionDO encodeQuestionDO = new EncodeQuestionDO();
        BeanUtils.copyProperties(addEncodeDTO,encodeQuestionDO);
        encodeQuestionDO.setCreateTime(LocalDateTime.now());
        encodeQuestionMapper.insert(encodeQuestionDO);
    }

    public void editAdd1(Integer encodeId) {
        encodeQuestionMapper.editAdd1(encodeId);
    }

    public void editMinus(Integer encodeId) {
        encodeQuestionMapper.editMinus(encodeId);

    }
}
